#include <WiFi.h>
#include <WiFiManager.h> // 需要安装 WiFiManager 库
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <TimeLib.h>
#include <GxEPD2_BW.h>
#include <Fonts/FreeMonoBold12pt7b.h>
#include <Fonts/FreeMonoBold18pt7b.h>
#include <Fonts/FreeMonoBold48pt7b.h>

// NTP 服务器
const char *ntpServer = "ntp.tencent.com";
// 同步间隔时间
const int syncInterval = 21600000; // 单位 ms
// NTP 客户端使用UDP
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, ntpServer, 28800, syncInterval); // 时间偏移为8小时（28800秒），更新时间间隔为6小时（21600000毫秒）

// 记录上次成功同步时间的时间戳
unsigned long lastSyncTime = 0;
// 记录前一分钟的时间
int previousMinute = -1;
// 记录上次全屏刷新的时间
unsigned long lastFullRefresh = 0;

// 初始化2.6寸墨水屏
GxEPD2_BW<GxEPD2_260, GxEPD2_260::HEIGHT> display(GxEPD2_260(/*CS=*/2, /*DC=*/17, /*RST=*/16, /*BUSY=*/4));

// 显示提示信息到墨水屏
void showMessage(const char *message)
{
  display.fillScreen(GxEPD_WHITE);
  display.setFont(&FreeMonoBold12pt7b);
  display.setCursor(10, 10); // 调整文本位置
  display.print(message);
  display.display();
}

// 显示连接Wi-Fi后的信息
void showWiFiConnected(const char *ssid)
{
  display.fillScreen(GxEPD_WHITE);
  display.setFont(&FreeMonoBold12pt7b);
  display.setCursor(10, 30);
  display.print("Wi-Fi Connected!");

  display.setCursor(10, 80);
  display.print("SSID:");
  display.setCursor(10, 120);
  display.print(ssid);

  display.display();
}

void syncTime()
{
  // 初始化NTP客户端并同步时间
  timeClient.begin();
  int attempts = 0;
  while (!timeClient.update() && attempts < 5)
  { // 最多尝试5次更新时间
    delay(1000);
    attempts++;
    Serial.println("获取时间失败，正在重试...");
  }

  if (attempts < 5)
  {
    unsigned long epochTime = timeClient.getEpochTime();
    setTime(epochTime);
    lastSyncTime = now();
    Serial.println("时间同步成功");
  }
  else
  {
    Serial.println("多次尝试后未能同步时间");
  }

  // 断开WiFi连接并关闭WiFi模块
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
  Serial.println("WiFi已关闭");
}

void show_time(char *dateString, char *timeString)
{
  // 打印当前日期到墨水屏
  display.setFont(&FreeMonoBold18pt7b);
  display.setCursor(0, 30); // 调整Y坐标以适应字体
  display.print(dateString);

  // 打印当前时间到墨水屏
  display.setFont(&FreeMonoBold48pt7b);
  display.setCursor(10, 120); // 调整Y坐标以适应字体
  display.print(timeString);

  // 串口打印时间
  Serial.println(dateString);
  Serial.println(timeString);
}

void setup()
{
  Serial.begin(115200);

  // 初始化墨水屏
  display.init();
  display.setRotation(1);
  display.setTextColor(GxEPD_BLACK);

  // 显示Wi-Fi配置提示信息
  showMessage("Configuring Wi-Fi...\nPlease connect to ESP32_AP to configure the network");

  // 使用WiFiManager进行WiFi配置
  WiFiManager wifiManager;

  // 清除WiFiManager的WIFI缓存
  // wifiManager.resetSettings();

  // 自动连接并配置Wi-Fi
  if (!wifiManager.autoConnect("ESP32_AP"))
  {
    showMessage("Failed to connect!");
    delay(3000);
    ESP.restart();
  }

  // 显示Wi-Fi连接成功信息以及SSID
  String ssid = WiFi.SSID();
  showWiFiConnected(ssid.c_str());
  delay(3000); // 短暂显示连接成功信息
  
  // 初始同步时间
  syncTime();

  // 初始化上次全屏刷新时间
  lastFullRefresh = millis();
}

void loop()
{
  // 检查是否需要同步时间
  if (now() - lastSyncTime > syncInterval)
  {             // 检查时间是否超过同步间隔
    syncTime(); // 同步时间
  }

  // 检测分钟变化
  if (minute() != previousMinute)
  {
    previousMinute = minute();

    // 将星期转换为缩写
    const char *weekDays[] = {"INV", "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
    const char *currentWeekdayName = weekDays[weekday()];

    // 格式化当前日期为字符串
    char dateString[30];
    snprintf(dateString, sizeof(dateString), "%04d-%02d-%02d %s",
             year(), month(), day(), currentWeekdayName);

    // 格式化当前时间为字符串
    char timeString[20];
    snprintf(timeString, sizeof(timeString), "%02d:%02d",
             hour(), minute());

    if (millis() - lastFullRefresh >= 600000)
    { // 每10分钟全屏刷新一次
      // 清除全屏
      display.fillScreen(GxEPD_WHITE);
      show_time(dateString, timeString);
      // 全屏刷新显示
      display.display();
      // 更新上次全屏刷新时间
      lastFullRefresh = millis();
    }
    else
    {
      // 清除显示区域
      display.setPartialWindow(0, 0, display.width(), display.height());
      display.fillScreen(GxEPD_WHITE);
      show_time(dateString, timeString);
      // 局部刷新显示
      display.display(true);
    }
  }

  // 休眠时间 00:00 - 7:00
  // 检测是否需要进入休眠状态
  if (hour() >= 0 && hour() < 7)
  {
    // 计算休眠时间（微秒）
    unsigned long sleepDuration = (7 - hour()) * 3600 * 1000000 - minute() * 60 * 1000000 - second() * 1000000;

    // 全屏刷新显示
    display.display();

    Serial.flush(); // 等待串口发送完成
    // 进入深度休眠模式直到7点
    esp_sleep_enable_timer_wakeup(sleepDuration);
    esp_deep_sleep_start();
    Serial.begin(115200);
  }
}
